package main

import (
	"fmt"
	"os"
	"strconv"
	"sync"

	"gitee.com/AlexWoo/arpc"
	"gitee.com/AlexWoo/arpc/atest/tester"
)

type uatype int

const (
	unknown uatype = iota
	uac
	uas
)

type opt struct {
	ut          uatype
	addr        string
	path        string
	script      string
	concurrency uint32
	total       uint32
}

func help() {
	fmt.Printf("%s -t uac -a addr -p path -f scriptfile [-c concurrency] [-n nrOfUac]\n", os.Args[0])
	fmt.Printf("%s -t uas -a addr -p path -f scriptfile\n", os.Args[0])
}

func parseOpt(o *opt) bool {
	if len(os.Args) == 1 {
		help()
		return false
	}

	opt := arpc.NewOptParser()
	for opt.GetOpt("t:a:p:f:c:n:") {
		switch opt.Opt() {
		case 't':
			ut := opt.OptVal()
			switch ut {
			case "uac":
				o.ut = uac
			case "uas":
				o.ut = uas
			default:
				fmt.Printf("unknown type %s\n\n", ut)
				help()
				return false
			}
		case 'a':
			o.addr = opt.OptVal()
		case 'p':
			o.path = opt.OptVal()
		case 'f':
			o.script = opt.OptVal()
		case 'c':
			con, err := strconv.ParseUint(opt.OptVal(), 10, 32)
			if err != nil {
				fmt.Printf("unexpected concurrency %s\n\n", opt.OptVal())
				help()
				return false
			}
			o.concurrency = uint32(con)
		case 'n':
			total, err := strconv.ParseUint(opt.OptVal(), 10, 32)
			if err != nil {
				fmt.Printf("unexpected nr of uac %s\n\n", opt.OptVal())
				help()
				return false
			}
			o.total = uint32(total)
		case '?':
			help()
			return false
		}
	}

	if o.ut == unknown {
		fmt.Printf("ua type not set\n\n")
		help()
		return false
	}

	if o.addr == "" {
		fmt.Printf("addr not set\n\n")
		help()
		return false
	}

	if o.path == "" {
		fmt.Printf("path not set\n\n")
		help()
		return false
	}

	if o.script == "" {
		fmt.Printf("script file not set\n\n")
		help()
		return false
	}

	if o.concurrency == 0 {
		o.concurrency = 1
	}

	if o.total == 0 {
		o.total = 1
	}

	return true
}

func main() {
	o := &opt{}
	if !parseOpt(o) {
		return
	}

	var c *tester.Client
	var wg sync.WaitGroup

	if o.ut == uac {
		c = tester.CreateTesterClient(&wg, o.addr, o.path, o.script, o.concurrency, o.total)
	} else {
		tester.CreateTesterServer(&wg, o.addr, o.path, o.script)
	}

	wg.Wait()

	if o.ut == uac {
		s, f, finish, totoal := c.Report()
		fmt.Printf("... UAC Tester Result --- successd: %d failed: %d total: %d hangup: %d\n",
			s, f, totoal, totoal-finish)
	}
}
